package core

import (
	"dfs/server/master/config"
	service "dfs/server/master/service/worker"
	"math"
	"strings"
)

type FileSystem struct {
	root *Node
}

func (fs *FileSystem) Init() {
	fs.root = &Node{
		Name:     "root",
		Type:     DIR,
		SubNodes: make(map[string]Node),
	}
}

func (fs *FileSystem) Get(url string) *Node {
	if url == "/" || url == "" {
		return fs.root
	}
	url = strings.Trim(url, "/ ")
	tokens := strings.Split(url, "/")
	var node *Node
	node = fs.root
	for _, token := range tokens {
		if node.Contains(token) {
			node = node.Cd(token)
		} else {
			return nil
		}
	}
	return node
}

func (fs *FileSystem) Put(url string, length int) ([]string, bool) {
	if url == "/" || url == "" {
		return nil, false
	}
	i := strings.LastIndex(url, "/")
	parent := fs.Get(url[:i])
	if parent == nil || parent.IsFile() || !parent.Touch(url[i+1:]) {
		// 父目录不存在 or 文件已存在
		return nil, false
	}
	node := parent.Cd(url[i+1:])
	num := int(math.Ceil(float64(length) / float64(config.BlockSize)))
	for i := 0; i < num; i++ {
		node.Blocks = append(node.Blocks, service.RandomWorker())
	}
	parent.Update(url[i+1:], node)
	return node.Blocks, true
}

func (fs *FileSystem) Mkdir(url string) bool {
	if url == "/" || url == "" {
		return false
	}
	i := strings.LastIndex(url, "/")
	parent := fs.Get(url[:i])
	if parent == nil || parent.IsFile() || !parent.Mkdir(url[i+1:]) {
		// 父目录不存在 or 目录已存在
		return false
	}
	return true
}

func (fs *FileSystem) Delete(url string) bool {
	if url == "/" || url == "" {
		return false
	}
	url = strings.Trim(url, "/ ")
	tokens := strings.Split(url, "/")
	var node *Node
	node = fs.root
	for i, token := range tokens {
		if node.Contains(token) {
			if i == len(tokens)-1 {
				return node.Rm(token)
			}
			node = node.Cd(token)
		} else {
			return false
		}
	}
	return false
}
